package org.moyrax.nereyda.lib
{
	import mx.collections.ArrayCollection;
	
	/**
	 * Esta colección permite mantener una lista de elementos
	 * asociados a una clave determinada de cualquier tipo.
	 * Para cada elemento podrá existir una sola clave, por lo
	 * que es excluyente.
	 */
	public class HashCollection extends ArrayCollection
	{
		protected var keyMap   :Array = [];
		protected var tableMap :Array = [];
		
		public function HashCollection( source:Array = null )
		{
			super(source);
		}

		/**
		 * Agrega un nuevo elemento a la colección.
		 * 
		 * @param key   Clave del elemento.
		 * @param value Elemento que se agregará vinculado a la clave.
		 */
		[Bindable("collectionChange")]
		
		public function put( key:Object, value:Object ):void 
		{
			var keyMapIndex :int = this.keyMap.indexOf( key );

			if ( keyMapIndex == -1 ) 
			{
				super.addItem( value );

				this.keyMap.push( key );
				this.tableMap.push( value );
			}
			else {
				this.tableMap[ keyMapIndex ] = value;
				this.setItemAt( value, keyMapIndex );
			}
		}

		/**
		 * Devuelve el elemento que corresponde a la clave especificada. 
		 * Si la clave no existe y el parámetro es un Integer, devuelve 
		 * el elemento que se encuentra en la posición indicada.
		 * 
		 * @param key Clave o índice del elemento.
		 */
		[Bindable("collectionChange")]

		public function get( key:Object ):Object 
		{
			var keyMapIndex :int = this.keyMap.indexOf( key );
			
			if ( keyMapIndex == -1 ) {
				if ( key is int ) {
					return( super.getItemAt( key as int ) );
				}
				
				return( null );
			}
			
			var tableObj  :Object = this.tableMap[ keyMapIndex ];
			var itemIndex :int = super.getItemIndex( tableObj );
			
			return( super.getItemAt( itemIndex ) );
		}

		/**
		 * Elimina el elemento vinculado a la clave especificada.
		 * 
		 * @param key Clave de referencia.
		 */
		[Bindable("collectionChange")]
		
		public function remove( key:Object ):Object 
		{
			var keyMapIndex :int = this.keyMap.indexOf( key );
			
			if ( keyMapIndex == -1 ) {
				return( null );
			}

			var tableObj  :Object = this.get( key );
			var itemIndex :int = super.getItemIndex( tableObj );
			
			this.keyMap.splice( keyMapIndex, 1 );
			this.tableMap.splice( keyMapIndex, 1 );

			return( super.removeItemAt( itemIndex ) );
		}
		
		/**
		 * Elimina todos los elementos.
		 */
		override public function removeAll():void
		{
			super.removeAll();

			this.keyMap   = [];
			this.tableMap = [];
		}
	}
}